package api

import (
	"encoding/json"
	"fmt"
	"getaway/basic/config"
	order "getaway/basic/proto/orderproto"
	"getaway/handler/response"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"net/http"
	"strconv"
	"sync"
	"time"
)

type Message struct {
	OrderId          string `json:"orderId" form:"orderId"`
	DriverId         int64  `json:"driverId" form:"driverId"`
	UserId           int64  `json:"userId" form:"userId"`
	Msg              string `json:"msg" form:"msg"`
	StartLoc         string `json:"startLoc" form:"startLoc"`
	EndLoc           string `json:"endLoc" form:"endLoc"`
	CarTypeId        int64  `json:"carTypeId" form:"carTypeId"`
	OrderType        int64  `json:"orderType" form:"orderType"`
	ServiceStartTime string `json:"serviceStartTime" form:"serviceStartTime"`
	CityId           int64  `json:"cityId" form:"cityId"`
	Source           string `json:"source" form:"source"`
	Status           int64  `json:"status" form:"status"`
	MsgType          string `json:"msgType" form:"msgType"`
}
type ChatMessage struct {
	OrderId    string `json:"orderId,omitempty"`    // 订单ID
	SendId     string `json:"sendId,omitempty"`     // 发送者ID
	SenderType string `json:"senderType,omitempty"` // 发送者类型（driver/user）
	Receiver   string `json:"receiver,omitempty"`   // 接收者ID
	Content    string `json:"content,omitempty"`    // 消息内容
	Timestamp  int64  `json:"timestamp,omitempty"`  // 消息发送时间戳
}

// WebSocket升级配置
var upgrader = websocket.Upgrader{
	ReadBufferSize:  4096, // 增加缓冲区大小
	WriteBufferSize: 4096,
	CheckOrigin:     func(r *http.Request) bool { return true }, // 生产环境需严格校验Origin
}

// 添加互斥锁保护全局连接映射
var nodeMutex sync.RWMutex

// 全局连接管理：司机节点（DriverID→*Node）、用户节点（UserID→*Node）
var DriverNode = make(map[string]*Node) // 司机节点：2个用法
var UserNode = make(map[string]*Node)   // 用户节点：1个用法

// 节点结构：包含连接、消息通道
type Node struct {
	Conn *websocket.Conn // WebSocket连接指针
	Data chan []byte     // 消息发送通道（缓冲大小可根据业务调整）
}

// 辅助函数：获取用户节点（带读锁保护）
func getUserNode(userID string) (*Node, bool) {
	nodeMutex.RLock()
	defer nodeMutex.RUnlock()
	node, ok := UserNode[userID]
	return node, ok
}

// 辅助函数：获取司机节点（带读锁保护）
func getDriverNode(driverID string) (*Node, bool) {
	nodeMutex.RLock()
	defer nodeMutex.RUnlock()
	node, ok := DriverNode[driverID]
	return node, ok
}

// 辅助函数：删除用户节点（带写锁保护）
func removeUserNode(userID string) {
	nodeMutex.Lock()
	defer nodeMutex.Unlock()
	delete(UserNode, userID)
}

// 辅助函数：删除司机节点（带写锁保护）
func removeDriverNode(driverID string) {
	nodeMutex.Lock()
	defer nodeMutex.Unlock()
	delete(DriverNode, driverID)
}

// 辅助函数：添加用户节点（带写锁保护）
func addUserNode(userID string, node *Node) {
	nodeMutex.Lock()
	defer nodeMutex.Unlock()
	UserNode[userID] = node
}

// 辅助函数：添加司机节点（带写锁保护）
func addDriverNode(driverID string, node *Node) {
	nodeMutex.Lock()
	defer nodeMutex.Unlock()
	DriverNode[driverID] = node
}

// 发送消息的辅助函数（处理连接错误和节点清理）
func sendMessage(node *Node, messageType int, data []byte) error {
	// 设置写入超时，避免阻塞过长时间
	if err := node.Conn.SetWriteDeadline(time.Now().Add(2 * time.Second)); err != nil {
		return err
	}

	// 直接发送消息，不经过通道缓冲，减少延迟
	return node.Conn.WriteMessage(messageType, data)
}

// 处理司机与乘客之间的聊天消息
func handleChatMessage(msg *ChatMessage) error {
	// 快速转发聊天消息
	if msg.SenderType == "driver" {
		// 司机发送消息给乘客
		node, ok := getUserNode(msg.Receiver)
		if !ok {
			return fmt.Errorf("乘客不在线: %s", msg.Receiver)
		}

		// 序列化聊天消息
		jsonData, err := json.Marshal(msg)
		if err != nil {
			return err
		}

		// 发送消息给乘客
		if err := sendMessage(node, websocket.TextMessage, jsonData); err != nil {
			removeUserNode(msg.Receiver) // 发送失败，移除节点
			return err
		}
	} else if msg.SenderType == "user" {
		// 乘客发送消息给司机
		node, ok := getDriverNode(msg.Receiver)
		if !ok {
			return fmt.Errorf("司机不在线: %s", msg.Receiver)
		}

		// 序列化聊天消息
		jsonData, err := json.Marshal(msg)
		if err != nil {
			return err
		}

		// 发送消息给司机
		if err := sendMessage(node, websocket.TextMessage, jsonData); err != nil {
			removeDriverNode(msg.Receiver) // 发送失败，移除节点
			return err
		}
	}
	return nil
}

func WSOrder(c *gin.Context) {
	// 1. WebSocket连接升级
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		response.SrvError(c, "升级失败", err.Error())
		return
	}
	defer conn.Close() // 关闭连接时的资源释放

	// 2. 解析用户ID并保存用户连接
	userID := c.Query("userId") // 从请求参数获取用户ID
	userNode := &Node{
		Conn: conn,
		Data: make(chan []byte, 50), // 初始化消息通道（可保留用于非聊天消息）
	}
	addUserNode(userID, userNode) // 使用带锁的辅助函数保存用户节点

	// 3. 循环读取用户消息（下单、聊天等）
	for {
		// 设置读取超时，避免连接长时间占用
		if err := conn.SetReadDeadline(time.Now().Add(60 * time.Second)); err != nil {
			removeUserNode(userID)
			return
		}

		_, data, err := conn.ReadMessage()
		if err != nil {
			removeUserNode(userID) // 连接断开时删除用户节点
			return
		}

		// 解析消息为基础结构体
		var baseMsg struct {
			MsgType string `json:"msgType"`
		}
		if err := json.Unmarshal(data, &baseMsg); err == nil {
			// 判断消息类型，优先处理聊天消息
			if baseMsg.MsgType == "chat" {
				// 处理聊天消息
				var chatMsg ChatMessage
				if err := json.Unmarshal(data, &chatMsg); err != nil {
					conn.WriteMessage(websocket.TextMessage, []byte("解析聊天消息失败: "+err.Error()))
					continue
				}
				// 设置必要字段
				chatMsg.SendId = userID
				chatMsg.SenderType = "user"
				chatMsg.Timestamp = time.Now().Unix()

				// 立即处理并转发聊天消息
				if err := handleChatMessage(&chatMsg); err != nil {
					conn.WriteMessage(websocket.TextMessage, []byte("发送消息失败: "+err.Error()))
				}
				continue
			}
		}

		// 处理订单相关消息
		var msg Message
		if err := json.Unmarshal(data, &msg); err != nil {
			conn.WriteMessage(websocket.TextMessage, []byte("解析消息失败: "+err.Error()))
			continue
		}

		// 处理下单逻辑（示例：调用订单服务创建订单）
		orderID, err := createOrder(c, msg, userID)
		if err != nil {
			conn.WriteMessage(websocket.TextMessage, []byte("创建订单失败: "+err.Error()))
			continue
		}

		// 向所有在线司机推送订单
		// 使用带锁的方式遍历司机节点
		nodeMutex.RLock()
		for driverID := range DriverNode {
			// 异步推送订单给司机，避免阻塞
			go pushOrderToDriver(driverID, orderID, msg, userID)
		}
		nodeMutex.RUnlock()

		// 立即通知用户订单已创建（不经过通道）
		orderMsg := map[string]interface{}{
			"type":          "order_created",
			"orderId":       orderID,
			"startLocation": msg.StartLoc,
			"endLocation":   msg.EndLoc,
			"status":        "pending",
		}
		jsonData, _ := json.Marshal(orderMsg)
		if err := sendMessage(userNode, websocket.TextMessage, jsonData); err != nil {
			removeUserNode(userID)
			return
		}
	}
}

// 辅助函数：创建订单
func createOrder(c *gin.Context, msg Message, userID string) (int64, error) {
	atoi, _ := strconv.Atoi(userID)
	req := &order.OrderCreateReq{
		UserId:           uint64(atoi),
		CarTypeId:        uint64(msg.CarTypeId),
		StartLoc:         msg.StartLoc,
		EndLoc:           msg.EndLoc,
		OrderType:        msg.OrderType,
		ServiceStartTime: msg.ServiceStartTime,
		CityId:           msg.CityId,
		Source:           msg.Source,
	}
	resp, err := config.OrderClient.OrderCreate(c, req)
	if err != nil {
		return 0, err
	}
	return int64(resp.Id), nil
}

// 辅助函数：向司机推送订单
func pushOrderToDriver(driverID string, orderID int64, msg Message, userID string) int64 {
	// 使用安全的辅助函数获取司机节点
	driverNode, ok := getDriverNode(driverID)
	if !ok {
		// 司机不在线，可做"订单回滚"或"推送至其他司机"逻辑
		return 0
	}
	// 构造订单消息并发送给司机
	orderMsg := map[string]interface{}{
		"type":     "new_order",
		"orderId":  orderID,
		"userId":   userID,
		"startLoc": msg.StartLoc,
		"endLoc":   msg.EndLoc,
		// 其他订单信息...
	}
	jsonData, err := json.Marshal(orderMsg)
	if err != nil {
		fmt.Println("pushOrderToDriver: JSON序列化失败:", err)
		return 0
	}
	// 直接发送消息，不经过通道，减少延迟
	if err := sendMessage(driverNode, websocket.TextMessage, jsonData); err != nil {
		removeDriverNode(driverID) // 发送失败，移除节点
		return 0
	}
	return orderID
}

func WSDriver(c *gin.Context) {
	// 1. WebSocket连接升级
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		response.SrvError(c, "升级失败", err.Error())
		return
	}

	// 2. 解析司机ID并保存司机连接
	driverID := c.Query("driverId")
	driverNode := &Node{
		Conn: conn,
		Data: make(chan []byte, 50), // 初始化消息通道（可保留用于非聊天消息）
	}
	addDriverNode(driverID, driverNode) // 使用带锁的辅助函数保存司机节点

	// 3. 循环读取司机消息（接单、聊天等）
	for {
		// 设置读取超时，避免连接长时间占用
		if err := conn.SetReadDeadline(time.Now().Add(60 * time.Second)); err != nil {
			removeDriverNode(driverID)
			return
		}

		_, data, err := conn.ReadMessage()
		if err != nil {
			removeDriverNode(driverID) // 连接断开时删除司机节点
			return
		}

		// 解析消息为基础结构体
		var baseMsg struct {
			MsgType string `json:"msgType"`
		}
		if err := json.Unmarshal(data, &baseMsg); err == nil {
			// 判断消息类型，优先处理聊天消息
			if baseMsg.MsgType == "chat" {
				// 处理聊天消息
				var chatMsg ChatMessage
				if err := json.Unmarshal(data, &chatMsg); err != nil {
					conn.WriteMessage(websocket.TextMessage, []byte("解析聊天消息失败: "+err.Error()))
					continue
				}
				// 设置必要字段
				chatMsg.SendId = driverID
				chatMsg.SenderType = "driver"
				chatMsg.Timestamp = time.Now().Unix()

				// 立即处理并转发聊天消息
				if err := handleChatMessage(&chatMsg); err != nil {
					conn.WriteMessage(websocket.TextMessage, []byte("发送消息失败: "+err.Error()))
				}
				continue
			}
		}

		// 处理订单相关消息
		var driverMsg map[string]interface{}
		if err := json.Unmarshal(data, &driverMsg); err != nil {
			conn.WriteMessage(websocket.TextMessage, []byte("解析司机消息失败: "+err.Error()))
			continue
		}

		// 判断消息类型，如果是订单接受
		msgType, msgTypeOk := driverMsg["type"].(string)
		if !msgTypeOk || msgType != "accept_order" {
			// 不是订单接受消息，继续处理
			orderID, ok := driverMsg["orderId"].(float64)
			if !ok {
				continue
			}
			handleDriverAccept(c, int64(orderID), driverID)
		} else {
			// 订单接受消息
			orderID, ok := driverMsg["orderId"].(float64)
			if !ok {
				continue
			}
			// 异步处理司机接单，避免阻塞聊天消息处理
			go handleDriverAccept(c, int64(orderID), driverID)
		}
	}
}

// 辅助函数：处理司机接单
func handleDriverAccept(c *gin.Context, orderID int64, driverID string) {
	// 转换driverID为int64类型
	driverIdInt, err := strconv.ParseInt(driverID, 10, 64)
	if err != nil {
		// 添加错误处理和日志
		fmt.Println("handleDriverAccept: 司机ID解析失败:", err)
		return
	}

	// 更新订单状态
	orderResp, err := config.OrderClient.UpdateOrderStatus(c, &order.UpdateOrderStatusReq{
		OrderId:  uint32(orderID),
		Status:   120, // 司机已接单状态码
		DriverId: driverIdInt,
		CityId:   1, // 示例城市ID，需从业务中获取
	})
	if err != nil {
		// 添加错误处理和日志
		fmt.Println("handleDriverAccept: 更新订单状态失败:", err)
		return
	}

	// 打印调试信息，确认订单更新成功
	fmt.Printf("handleDriverAccept: 订单%d状态更新成功，司机ID:%s，用户ID:%d\n", orderID, driverID, orderResp.UserId)

	// 通知用户"司机已接单"
	// 先查询用户ID
	userIdStr := strconv.FormatInt(orderResp.UserId, 10)
	userNode, ok := getUserNode(userIdStr)
	if ok {
		fmt.Printf("handleDriverAccept: 找到用户节点，用户ID:%s\n", userIdStr)
		// 构建通知消息
		notifyMsg := map[string]interface{}{
			"type":     "order_accepted",
			"orderId":  orderID,
			"driverId": driverID,
			"status":   "accepted",
		}
		jsonData, err := json.Marshal(notifyMsg)
		if err != nil {
			fmt.Println("handleDriverAccept: JSON序列化失败:", err)
			return
		}
		// 使用优化的sendMessage函数发送消息给用户
		if err := sendMessage(userNode, websocket.TextMessage, jsonData); err != nil {
			fmt.Println("handleDriverAccept: 发送消息给用户失败:", err)
			// 发送失败时删除用户节点
			removeUserNode(userIdStr)
		}
	} else {
		fmt.Printf("handleDriverAccept: 未找到用户节点，用户ID:%s\n", userIdStr)
	}

	// 通知司机自己接单成功，更新司机端的订单状态
	driverNode, driverOk := getDriverNode(driverID)
	if driverOk {
		fmt.Printf("handleDriverAccept: 找到司机节点，司机ID:%s\n", driverID)
		// 构建司机通知消息
		driverNotifyMsg := map[string]interface{}{
			"type":     "order_accepted",
			"orderId":  orderID,
			"driverId": driverID,
			"status":   "accepted",
		}
		driverJsonData, err := json.Marshal(driverNotifyMsg)
		if err != nil {
			fmt.Println("handleDriverAccept: 司机消息JSON序列化失败:", err)
			return
		}
		// 使用优化的sendMessage函数发送消息给司机
		if err := sendMessage(driverNode, websocket.TextMessage, driverJsonData); err != nil {
			fmt.Println("handleDriverAccept: 发送消息给司机失败:", err)
			// 发送失败时删除司机节点
			removeDriverNode(driverID)
		}
	} else {
		fmt.Printf("handleDriverAccept: 未找到司机节点，司机ID:%s\n", driverID)
	}
}
